using MQTTnet;

namespace Digitalmes.Infrastructure.MQ.Mqtt;

/// <summary>
/// MQTT 客户端实现。
/// </summary>
internal sealed class DefaultMQTTClient : IMQTTClient
{
    private readonly MqttClientOptions _mqttClientOptions;
    private readonly IMqttClient _mqttClient;

    public DefaultMQTTClient(IOptions<MqttOptions> options)
    {
        var options2 = options.Value;

        var mqttClientOptionsBuilder = new MqttClientOptionsBuilder()
            .WithTcpServer(options2.Host, options2.Port);
        if (!string.IsNullOrEmpty(options2.Username))
        {
            mqttClientOptionsBuilder.WithCredentials(options2.Username, options2.Password);
        }
        if (!string.IsNullOrEmpty(options2.ClientId))
        {
            mqttClientOptionsBuilder.WithClientId(options2.ClientId);
        }
        if (options2.QoS.HasValue)
        {
            mqttClientOptionsBuilder.WithWillQualityOfServiceLevel(options2.QoS.Value);
        }
        if (options2.ProtocolVersion.HasValue)
        {
            mqttClientOptionsBuilder.WithProtocolVersion(options2.ProtocolVersion.Value);
        }
        if (options2.Retain.HasValue)
        {
            mqttClientOptionsBuilder.WithWillRetain(options2.Retain.Value);
        }
        if (options2.KeepAlivePeriod > 0)
        {
            mqttClientOptionsBuilder.WithKeepAlivePeriod(TimeSpan.FromSeconds(options2.KeepAlivePeriod.Value));
        }
        if (options2.Timeout.HasValue)
        {
            mqttClientOptionsBuilder.WithTimeout(TimeSpan.FromSeconds(options2.Timeout.Value));
        }

        _mqttClientOptions = mqttClientOptionsBuilder.Build();

        var factory = new MqttClientFactory();
        _mqttClient = factory.CreateMqttClient();

        // 重连
        //_mqttClient.DisconnectedAsync += async e =>
        //{
        //    Console.WriteLine("### DISCONNECTED FROM SERVER ###");
        //    await Task.Delay(TimeSpan.FromSeconds(5));

        //    if (e.ClientWasConnected)
        //    {
        //        try
        //        {
        //            // 重新连接
        //            await _mqttClient.ReconnectAsync();
        //        }
        //        catch
        //        {
        //        }
        //    }
        //};

        // 接收消息事件处理
        //_mqttClient.ApplicationMessageReceivedAsync += e =>
        //{
        //    Console.WriteLine("### RECEIVED APPLICATION MESSAGE ###");
        //    Console.WriteLine($"+ Topic = {e.ApplicationMessage.Topic}");
        //    Console.WriteLine($"+ Payload = {e.ApplicationMessage.ConvertPayloadToString()}");
        //    Console.WriteLine($"+ QoS = {e.ApplicationMessage.QualityOfServiceLevel}");
        //    Console.WriteLine($"+ Retain = {e.ApplicationMessage.Retain}");
        //    Console.WriteLine();

        //    return Task.CompletedTask;
        //};

        // 连接成功后订阅主题
        //_mqttClient.ConnectedAsync += async e =>
        //{
        //    await _mqttClient.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("my/topic").Build());
        //};
    }

    public async Task<bool> ConnectAsync(CancellationToken cancellationToken = default)
    {
        if (!_mqttClient.IsConnected)
        {
            var connectResult = await _mqttClient.ConnectAsync(_mqttClientOptions, cancellationToken);
            return connectResult.ResultCode is MqttClientConnectResultCode.Success;
        }

        return true;
    }

    public async Task<bool> PublishStringAsync(string topic, string payload, bool retain = false, CancellationToken cancellationToken = default)
    {
        if (!await ConnectAsync(cancellationToken))
        {
            return false;
        }

        var publishResult = await _mqttClient.PublishStringAsync(topic, payload, retain: retain, cancellationToken: cancellationToken);
        return publishResult.IsSuccess;
    }

    public void Dispose()
    {
        _mqttClient.Dispose();
    }
}
